<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>测试前验证</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#36D399',
                        warning: '#FF9F43',
                        danger: '#F43F5E',
                        neutral: {
                            100: '#F9FAFB',
                            200: '#F3F4F6',
                            300: '#E5E7EB',
                            400: '#D1D5DB',
                            500: '#9CA3AF',
                            600: '#6B7280',
                            700: '#4B5563',
                            800: '#374151',
                            900: '#1F2937',
                        }
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                    boxShadow: {
                        'card': '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
                        'btn': '0 4px 6px -1px rgba(22, 93, 255, 0.2), 0 2px 4px -1px rgba(22, 93, 255, 0.1)',
                        'modal': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
                    }
                },
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .text-shadow {
                text-shadow: 0 2px 4px rgba(0,0,0,0.1);
            }
            .bg-gradient-primary {
                background: linear-gradient(135deg, #165DFF 0%, #4080FF 100%);
            }
            .transition-custom {
                transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
            }
            .hover-scale {
                transition: transform 0.2s ease;
            }
            .hover-scale:hover {
                transform: scale(1.03);
            }
            .card-enter {
                animation: cardEnter 0.6s ease-out forwards;
            }
            @keyframes cardEnter {
                from {
                    opacity: 0;
                    transform: translateY(20px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
            .pulse-ring {
                position: relative;
            }
            .pulse-ring::after {
                content: '';
                position: absolute;
                top: 0;
                left: 0;
                right: 0;
                bottom: 0;
                border-radius: inherit;
                border: 2px solid theme('colors.primary');
                animation: pulse 2s infinite;
            }
            @keyframes pulse {
                0% {
                    transform: scale(1);
                    opacity: 1;
                }
                70% {
                    transform: scale(1.1);
                    opacity: 0;
                }
                100% {
                    transform: scale(1.1);
                    opacity: 0;
                }
            }
            .modal-enter {
                animation: modalEnter 0.3s ease-out forwards;
            }
            @keyframes modalEnter {
                from {
                    opacity: 0;
                    transform: translateY(10px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
            .backdrop-blur {
                backdrop-filter: blur(8px);
            }
            .hidden {
                display: none;
            }
            .animate-shake {
                animation: shake 0.5s ease-in-out;
            }
            @keyframes shake {
                0%, 100% { transform: translateX(0); }
                10%, 30%, 50%, 70%, 90% { transform: translateX(-5px); }
                20%, 40%, 60%, 80% { transform: translateX(5px); }
            }
            .success {
                color: #36D399;
            }
            .error {
                color: #F43F5E;
            }
            .warning {
                color: #FF9F43;
            }
            .recording-indicator {
                display: inline-block;
                width: 10px;
                height: 10px;
                background-color: #F43F5E;
                border-radius: 50%;
                margin-right: 5px;
                animation: pulse 1.5s infinite;
            }
			}
        </style>
</head>
<body class="font-inter bg-gradient-to-br from-neutral-100 to-neutral-200 min-h-screen flex items-center justify-center p-4">
    <div class="max-w-4xl w-full mx-auto">
        <!-- 头部信息 -->
        <div class="text-center mb-8 card-enter">
            <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-neutral-800 mb-2 text-shadow">
                <i class="fa fa-shield text-primary mr-2"></i>测试前验证
            </h1>
            <p class="text-neutral-600 max-w-2xl mx-auto">请完成以下验证步骤，以确保测试环境安全且符合要求</p>
        </div>

        <!-- 主内容卡片 -->
        <div class="bg-white rounded-2xl shadow-card overflow-hidden card-enter" style="animation-delay: 0.1s">
            <div class="bg-gradient-primary p-6 text-white">
                <h2 class="text-xl font-semibold flex items-center">
                    <i class="fa fa-user-circle mr-2"></i>身份验证
                </h2>
                <p class="text-blue-100 text-sm mt-1">请完成以下两项验证，以确认是您本人在进行测试</p>
            </div>

            <!-- 验证步骤 -->
            <div class="p-6 grid grid-cols-1 md:grid-cols-2 gap-6">
                <!-- 摄像头拍照部分 -->
                <div class="bg-neutral-50 rounded-xl p-5 hover-scale border border-neutral-200">
                    <div class="flex items-center mb-4">
                        <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-primary">
                            <i class="fa fa-video-camera"></i>
                        </div>
                        <h3 class="ml-3 text-lg font-medium text-neutral-800">摄像头拍照</h3>
                    </div>
                    <p class="text-sm text-neutral-600 mb-4">请确保光线充足，面部清晰可见</p>
                    
                    <div class="relative mb-4">
                        <div class="aspect-square bg-neutral-100 rounded-lg overflow-hidden flex items-center justify-center">
                            <video id="cameraVideo" class="w-full h-full object-cover" autoplay muted></video>
                            <div id="cameraPlaceholder" class="absolute inset-0 flex flex-col items-center justify-center bg-neutral-100">
                                <i class="fa fa-camera text-neutral-400 text-4xl mb-2"></i>
                                <p class="text-neutral-500 text-sm">等待摄像头权限...</p>
                            </div>
                        </div>
                        <canvas id="captureCanvas" class="hidden"></canvas>
                    </div>
                    
                    <button id="captureBtn" class="w-full py-3 bg-primary text-white rounded-lg hover:bg-primary/90 transition-custom flex items-center justify-center">
                        <i class="fa fa-camera mr-2"></i>
                        <span>点击拍照</span>
                    </button>
                    <p id="captureStatus" class="text-xs text-neutral-500 mt-2 text-center">未拍摄照片</p>
                </div>

                <!-- 声纹录入部分 -->
                <div class="bg-neutral-50 rounded-xl p-5 hover-scale border border-neutral-200">
                    <div class="flex items-center mb-4">
                        <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-primary">
                            <i class="fa fa-microphone"></i>
                        </div>
                        <h3 class="ml-3 text-lg font-medium text-neutral-800">声纹录入</h3>
                    </div>
                    <p class="text-sm text-neutral-600 mb-4">请朗读以下文字进行声纹验证</p>
                    
                    <div class="bg-white p-4 rounded-lg border border-neutral-200 mb-4">
                        <p class="text-neutral-700 text-center">"测试系统正在验证我的身份，请确认是本人操作"</p>
                    </div>
                    
                    <div class="recorder-container">
                        <div class="recorder-controls flex gap-2 mb-2">
                            <button id="startRecordBtn" class="flex-1 py-2 bg-secondary text-white rounded-lg hover:bg-secondary/90 transition-custom flex items-center justify-center">
                                <i class="fa fa-microphone mr-2"></i> 开始录音
                            </button>
                            <button id="stopRecordBtn" class="flex-1 py-2 bg-danger text-white rounded-lg hover:bg-danger/90 transition-custom flex items-center justify-center" disabled>
                                <i class="fa fa-stop mr-2"></i> 停止录音
                            </button>
                        </div>
                        <div id="recordingStatus" class="text-sm text-danger mb-2 hidden">
                            <span class="recording-indicator"></span>正在录音...请对着麦克风说话
                        </div>
                        <div id="audioPreview" class="hidden">
                            <div class="flex justify-between items-center mb-2">
                                <h6 class="text-sm font-medium text-neutral-700">录音预览</h6>
                                <button id="verifyBtn" class="py-1 px-3 bg-primary text-white rounded text-sm hover:bg-primary/90 transition-custom">
                                    <i class="fa fa-paper-plane mr-1"></i>验证声纹
                                </button>
                            </div>
                            <audio id="audioPlayer" controls class="w-full mb-2"></audio>
                            <div class="flex justify-between text-xs text-neutral-500">
                                <span>格式: WAV</span>
                                <span>采样率: 16kHz | 位长: 16bit | 单声道</span>
                            </div>
                        </div>
                        <div id="voiceResult" class="mt-2 text-sm text-center hidden"></div>
                    </div>
                    <p id="recordStatus" class="text-xs text-neutral-500 mt-2 text-center">未录制声音</p>
                </div>
            </div>

            <!-- 进度指示器 -->
            <div class="p-6 pt-0">
                <div class="flex items-center justify-between mb-2">
                    <span class="text-sm text-neutral-600">验证进度</span>
                    <span id="progressText" class="text-sm font-medium text-primary">0%</span>
                </div>
                <div class="h-2 bg-neutral-200 rounded-full overflow-hidden">
                    <div id="progressBar" class="h-full bg-primary rounded-full transition-all duration-500" style="width: 0%"></div>
                </div>
            </div>

            <!-- 操作按钮 -->
            <div class="p-6 border-t border-neutral-200 flex flex-col sm:flex-row justify-center gap-4">
                <button id="resetBtn" class="py-3 px-6 border border-neutral-300 text-neutral-700 rounded-lg hover:bg-neutral-50 transition-custom flex items-center justify-center">
                    <i class="fa fa-refresh mr-2"></i>
                    <span>重新验证</span>
                </button>
                <button id="enterTestBtn" class="py-3 px-8 bg-primary text-white rounded-lg hover:bg-primary/90 transition-custom shadow-btn flex items-center justify-center" disabled>
                    <i class="fa fa-arrow-right mr-2"></i>
                    <span>进入测试</span>
                </button>
            </div>
        </div>

        <!-- 页脚信息 -->
        <div class="text-center mt-6 text-neutral-500 text-sm card-enter" style="animation-delay: 0.2s">
            <p>验证过程仅用于确保测试环境安全，不会存储您的个人信息</p>
        </div>
    </div>

    <!-- 模态框容器 -->
    <div id="modalContainer" class="fixed inset-0 flex items-center justify-center z-50 hidden">
        <div class="absolute inset-0 bg-black/50 backdrop-blur" id="modalBackdrop"></div>
        <div class="bg-white rounded-xl shadow-modal p-6 max-w-md w-full mx-4 z-10 modal-enter" id="modalContent">
            <div id="modalIcon" class="w-16 h-16 mx-auto mb-4 rounded-full flex items-center justify-center bg-red-100">
                <i class="fa fa-exclamation-triangle text-red-500 text-2xl"></i>
            </div>
            <h3 id="modalTitle" class="text-xl font-semibold text-center text-neutral-800 mb-2">请完成验证</h3>
            <p id="modalMessage" class="text-neutral-600 text-center mb-6">您还未完成所有验证步骤，请继续完成拍照和声纹验证。</p>
            <button id="modalCloseBtn" class="w-full py-3 bg-primary text-white rounded-lg hover:bg-primary/90 transition-custom">
                确定
            </button>
        </div>
    </div>

    <script>
        // 摄像头相关变量
        const cameraVideo = document.getElementById('cameraVideo');
        const captureCanvas = document.getElementById('captureCanvas');
        const captureBtn = document.getElementById('captureBtn');
        const cameraPlaceholder = document.getElementById('cameraPlaceholder');
        const captureStatus = document.getElementById('captureStatus');
        let mediaStream = null;
        let isCameraReady = false;
        let isPhotoVerified = false;

        // 录音相关变量
        const startRecordBtn = document.getElementById('startRecordBtn');
        const stopRecordBtn = document.getElementById('stopRecordBtn');
        const verifyBtn = document.getElementById('verifyBtn');
        const recordingStatus = document.getElementById('recordingStatus');
        const audioPlayer = document.getElementById('audioPlayer');
        const audioPreview = document.getElementById('audioPreview');
        const voiceResult = document.getElementById('voiceResult');
        const recordStatus = document.getElementById('recordStatus');
        let mediaRecorder = null;
        let audioChunks = [];
        let isRecording = false;
        let isVoiceVerified = false;
        let audioBlob = null;

        // 进度相关
        const progressBar = document.getElementById('progressBar');
        const progressText = document.getElementById('progressText');
        const enterTestBtn = document.getElementById('enterTestBtn');
        const resetBtn = document.getElementById('resetBtn');
        let verificationProgress = 0;
        let image_from_database = null;
        
        // 模态框相关
        const modalContainer = document.getElementById('modalContainer');
        const modalContent = document.getElementById('modalContent');
        const modalIcon = document.getElementById('modalIcon');
        const modalTitle = document.getElementById('modalTitle');
        const modalMessage = document.getElementById('modalMessage');
        const modalCloseBtn = document.getElementById('modalCloseBtn');
        const modalBackdrop = document.getElementById('modalBackdrop');
        
        // 更新进度条
        function updateProgress(progress) {
            verificationProgress = progress;
            progressBar.style.width = `${progress}%`;
            progressText.textContent = `${progress}%`;
            
            // 只有当两个验证都完成时，才能进入测试
            if (isPhotoVerified && isVoiceVerified) {
                enterTestBtn.disabled = false;
                enterTestBtn.classList.add('pulse-ring');
            } else {
                enterTestBtn.disabled = true;
                enterTestBtn.classList.remove('pulse-ring');
            }
        }

        // 显示模态框
        function showModal(type, title, message) {
            // 设置模态框内容
            if (type === 'error') {
                modalIcon.className = 'w-16 h-16 mx-auto mb-4 rounded-full flex items-center justify-center bg-red-100';
                modalIcon.innerHTML = '<i class="fa fa-exclamation-triangle text-red-500 text-2xl"></i>';
            } else if (type === 'success') {
                modalIcon.className = 'w-16 h-16 mx-auto mb-4 rounded-full flex items-center justify-center bg-green-100';
                modalIcon.innerHTML = '<i class="fa fa-check-circle text-green-500 text-2xl"></i>';
            }
            
            modalTitle.textContent = title;
            modalMessage.textContent = message;
            
            // 显示模态框
            modalContainer.classList.remove('hidden');
            document.body.style.overflow = 'hidden'; // 防止背景滚动
        }

        // 隐藏模态框
        function hideModal() {
            modalContainer.classList.add('hidden');
            document.body.style.overflow = ''; // 恢复背景滚动
        }
        
        function loadUserInfo() {
            const username = sessionStorage.getItem('username');
            if (!username) {
                window.location.href = 'login.html';
                return;
            } else {
                const name = {"Name": username};
                const jsonData = JSON.stringify(name);
                fetch("http://127.0.0.1:5003/imagebase", {
                    method: "POST",
                    headers: {
                        "Content-Type": "application/json"
                    },
                    body: jsonData,
                })
                .then(response => response.json())
                .then(data => {
                    image_from_database = data.Image;
                });
            }
        }

        // 尝试获取摄像头媒体流并显示到video
        function initCamera() {
            if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
                navigator.mediaDevices.getUserMedia({ video: true })
                    .then(stream => {
                        mediaStream = stream;
                        cameraVideo.srcObject = stream;
                        cameraVideo.onloadedmetadata = () => {
                            isCameraReady = true;
                            cameraPlaceholder.classList.add('hidden');
                            captureStatus.textContent = '摄像头已就绪，点击拍照';
                            captureStatus.classList.remove('text-red-500');
                            captureStatus.classList.add('text-green-500');
                        };
                    })
                    .catch(err => {
                        console.error('获取摄像头失败:', err);
                        cameraPlaceholder.innerHTML = `
                            <i class="fa fa-exclamation-triangle text-red-500 text-4xl mb-2"></i>
                            <p class="text-red-500 text-sm text-center">无法访问摄像头，请确保已授予权限</p>
                        `;
                        captureStatus.textContent = '摄像头访问失败';
                        captureStatus.classList.add('text-red-500');
                    });
            } else {
                cameraPlaceholder.innerHTML = `
                    <i class="fa fa-exclamation-triangle text-red-500 text-4xl mb-2"></i>
                    <p class="text-red-500 text-sm text-center">您的浏览器不支持摄像头功能</p>
                `;
                captureStatus.textContent = '浏览器不支持摄像头';
                captureStatus.classList.add('text-red-500');
            }
        }

        // 拍照功能
        captureBtn.addEventListener('click', () => {
            if (!isCameraReady) return;
            
            const context = captureCanvas.getContext('2d');
            captureCanvas.width = cameraVideo.videoWidth;
            captureCanvas.height = cameraVideo.videoHeight;
            context.drawImage(cameraVideo, 0, 0, captureCanvas.width, captureCanvas.height);
            
            // 转换为Base64
            capturedImage = captureCanvas.toDataURL('image/jpeg');
            const imageData = capturedImage.split(',')[1]; 
            const imageBase = {"image1": image_from_database, "image2": imageData};
            const imageJson = JSON.stringify(imageBase);
            
            fetch("http://127.0.0.1:5003/image", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({data: imageJson}),
            })
            .then(response => response.json())
            .then(data => {
                console.log(data.error_code);
                if (data.error_code != 0) {
                    showModal('error', '验证失败', '请正确放置摄像头');
                } else {
                    console.log("匹配分数" + data.result.score);
                    if (data.result.score < 80) {
                        showModal('error', '验证失败', '请本人考试');
                    } else {
                        setTimeout(() => {
                            isPhotoVerified = true;
                            captureStatus.textContent = '照片验证成功';
                            captureStatus.classList.remove('text-primary');
                            captureStatus.classList.add('text-green-500');
                            captureBtn.innerHTML = '<i class="fa fa-check mr-2"></i><span>已拍照</span>';
                            captureBtn.classList.remove('bg-primary');
                            captureBtn.classList.add('bg-green-500');
                            
                            // 更新进度
                            updateProgress(isVoiceVerified ? 100 : 50);
                        }, 1500);
                    }
                }
            });
        });

        // 开始录音
        startRecordBtn.addEventListener('click', () => {
            if (isRecording) return;
            
            audioChunks = [];
            startRecordBtn.disabled = true;
            stopRecordBtn.disabled = false;
            recordingStatus.classList.remove('hidden');
            recordStatus.textContent = '正在录音...';
            recordStatus.classList.remove('text-red-500');
            recordStatus.classList.add('text-primary');
            
            navigator.mediaDevices.getUserMedia({ audio: true })
                .then(stream => {
                    isRecording = true;
                    mediaRecorder = new MediaRecorder(stream);
                    
                    mediaRecorder.ondataavailable = event => {
                        if (event.data.size > 0) {
                            audioChunks.push(event.data);
                        }
                    };
                    
                    mediaRecorder.onstop = () => {
                        isRecording = false;
                        audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
                        
                        // 创建音频URL并设置预览
                        const audioUrl = URL.createObjectURL(audioBlob);
                        audioPlayer.src = audioUrl;
                        
                        // 显示预览
                        audioPreview.classList.remove('hidden');
                        verifyBtn.disabled = false;
                        
                        recordStatus.textContent = '录音完成，请验证';
                        recordingStatus.classList.add('hidden');
                        stopRecordBtn.disabled = true;
                        
                        // 停止所有音轨
                        stream.getTracks().forEach(track => track.stop());
                    };
                    
                    mediaRecorder.start();
                })
                .catch(err => {
                    console.error('获取麦克风失败:', err);
                    recordStatus.textContent = '麦克风访问失败';
                    recordStatus.classList.add('text-red-500');
                    startRecordBtn.disabled = false;
                    stopRecordBtn.disabled = true;
                    recordingStatus.classList.add('hidden');
                });
        });

        // 停止录音
        stopRecordBtn.addEventListener('click', () => {
            if (isRecording && mediaRecorder) {
                mediaRecorder.stop();
                stopRecordBtn.disabled = true;
            }
        });

        // 验证声纹
        verifyBtn.addEventListener('click', () => {
            if (!audioBlob) return;
            
            verifyBtn.disabled = true;
            recordStatus.textContent = '正在验证声纹...';
            
            // 模拟API请求延迟
            setTimeout(() => {
                // 随机生成验证结果（模拟）
                const isSuccess = Math.random() > 0.3; // 70%成功率
                
                if (isSuccess) {
                    isVoiceVerified = true;
                    recordStatus.textContent = '声纹验证成功';
                    recordStatus.classList.remove('text-primary');
                    recordStatus.classList.add('text-green-500');
                    voiceResult.textContent = '声纹匹配成功，验证通过';
                    voiceResult.classList.remove('error', 'hidden');
                    voiceResult.classList.add('success');
                    
                    // 更新进度
                    updateProgress(isPhotoVerified ? 100 : 50);
                } else {
                    recordStatus.textContent = '声纹验证失败';
                    recordStatus.classList.add('text-red-500');
                    voiceResult.textContent = '声纹不匹配，请重新录制';
                    voiceResult.classList.remove('success', 'hidden');
                    voiceResult.classList.add('error');
                    verifyBtn.disabled = false;
                }
            }, 2000);
        });

        // 重新验证
        resetBtn.addEventListener('click', () => {
            // 重置拍照状态
            isPhotoVerified = false;
            captureBtn.innerHTML = '<i class="fa fa-camera mr-2"></i><span>点击拍照</span>';
            captureBtn.classList.remove('bg-green-500');
            captureBtn.classList.add('bg-primary');
            captureBtn.disabled = false;
            captureStatus.textContent = '摄像头已就绪，点击拍照';
            captureStatus.classList.remove('text-red-500');
            captureStatus.classList.add('text-green-500');
            
            // 重置录音状态
            isVoiceVerified = false;
            audioBlob = null;
            startRecordBtn.innerHTML = '<i class="fa fa-microphone mr-2"></i><span>开始录音</span>';
            startRecordBtn.classList.remove('bg-green-500');
            startRecordBtn.classList.add('bg-secondary');
            startRecordBtn.disabled = false;
            stopRecordBtn.disabled = true;
            verifyBtn.disabled = true;
            recordStatus.textContent = '未录制声音';
            recordStatus.classList.remove('text-green-500', 'text-primary', 'text-red-500');
            recordStatus.classList.add('text-neutral-500');
            recordingStatus.classList.add('hidden');
            audioPreview.classList.add('hidden');
            voiceResult.classList.add('hidden');
            audioPlayer.src = '';
            
            // 重置进度
            updateProgress(0);
            
            // 如果正在录音，停止
            if (isRecording && mediaRecorder) {
                mediaRecorder.stop();
            }
        });

        // 进入测试 - 修改后的点击事件
        enterTestBtn.addEventListener('click', () => {
            if (isPhotoVerified && isVoiceVerified) {
                // 显示成功模态框
                showModal('success', '验证成功', '您已成功完成所有验证步骤，即将进入测试！');
                
                // 2秒后跳转到test.html
                setTimeout(() => {
                    hideModal();
                    window.location.href = 'test(6).html';  // 跳转到测试页面
                }, 2000);
            } else {
                // 显示错误模态框，提示未完成的步骤
                let missingSteps = [];
                if (!isPhotoVerified) missingSteps.push('拍照');
                if (!isVoiceVerified) missingSteps.push('声纹验证');
                
                showModal('error', '请完成验证', `您还未完成以下验证步骤：${missingSteps.join('和')}，请继续完成。`);
            }
        });

        // 关闭模态框
        modalCloseBtn.addEventListener('click', hideModal);
        modalBackdrop.addEventListener('click', hideModal);

        // 初始化摄像头
        initCamera();
        loadUserInfo();
    </script>
</body>
</html>